Skip to content

feat: add MiniMax as first-class provider with M2.7 models and native thinking support#2155

Open
octo-patch wants to merge 3 commits intorouter-for-me:mainfrom
octo-patch:feature/add-minimax-provider
Open

feat: add MiniMax as first-class provider with M2.7 models and native thinking support#2155
octo-patch wants to merge 3 commits intorouter-for-me:mainfrom
octo-patch:feature/add-minimax-provider

Conversation

@octo-patch
Copy link

@octo-patch octo-patch commented Mar 15, 2026

Summary

  • Add MiniMax as a first-class provider with OpenAI-compatible API integration
  • Register MiniMax-M2.7 and M2.7-highspeed models (1M context, 8K output) as primary models
  • Retain MiniMax-M2.5 and M2.5-highspeed models for backward compatibility
  • Native reasoning_split thinking mode support for all MiniMax models
  • Dedicated MiniMax thinking provider with proper boolean toggle conversion

Models Added

Model Context Max Output Notes
MiniMax-M2.7 1M tokens 8,192 Latest flagship model
MiniMax-M2.7-highspeed 1M tokens 8,192 Fast inference variant
MiniMax-M2.5 204K tokens 16,384 Previous generation
MiniMax-M2.5-highspeed 204K tokens 16,384 Previous fast variant

Test Plan

  • JSON model registry validated
  • config.example.yaml updated with M2.7 models
  • Existing thinking conversion tests pass (generic minimax-test model)
  • M2.7 and M2.7-highspeed verified against live MiniMax API

Add comprehensive MiniMax provider integration:

- Register MiniMax-M2.5 and MiniMax-M2.5-highspeed models in the model
  registry with 204K context length and thinking capability metadata
- Create dedicated MiniMax thinking provider that handles the native
  reasoning_split boolean toggle format, converting from budget/level
  modes to on/off semantics
- Enhance ApplyThinking to prefer provider-key-specific thinking appliers
  over generic format appliers, enabling MiniMax (and future providers)
  to work correctly when configured through openai-compatibility
- Add MiniMax thinking config extraction with fallback to OpenAI format
- Add MiniMax to thinking config stripping for non-thinking models
- Add MiniMax constant to provider identifiers
- Add MiniMax configuration example in config.example.yaml showing
  setup via openai-compatibility with base URL and model definitions
- Update README.md and README_CN.md with MiniMax support documentation
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates MiniMax as a first-class provider into the CLIProxyAPI, allowing users to leverage MiniMax models with native thinking capabilities through an OpenAI-compatible configuration. The core of the change involves adapting the system to MiniMax's unique reasoning_split boolean thinking format, ensuring seamless operation alongside existing providers by enhancing the thinking application and configuration extraction mechanisms.

Highlights

  • MiniMax Provider Support: Added comprehensive support for MiniMax models (MiniMax-M2.5, MiniMax-M2.5-highspeed) to CLIProxyAPI, including their unique reasoning_split thinking configuration.
  • Model Registry Update: Included MiniMax-M2.5 and MiniMax-M2.5-highspeed in models.json with their respective context lengths and thinking capability metadata.
  • Dedicated Thinking Provider: Implemented a specific thinking provider for MiniMax (internal/thinking/provider/minimax/) to manage its native reasoning_split boolean toggle format, converting generic thinking modes to on/off semantics.
  • Enhanced Thinking System: Improved the ApplyThinking logic to prioritize provider-key-specific thinking appliers over generic format appliers, ensuring correct handling for providers like MiniMax with custom thinking formats when configured via openai-compatibility.
  • Configuration Extraction: Introduced MiniMax-specific thinking configuration extraction, with a fallback to the OpenAI format, supporting both reasoning_split and reasoning_effort input formats.
  • Configuration Example: Provided a MiniMax configuration example in config.example.yaml to guide users.
  • Documentation Updates: Updated README.md and README_CN.md to reflect the new MiniMax provider support.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Updated the main description to include MiniMax as a compatible API interface.
    • Added MiniMax support with native reasoning_split thinking to the features list.
  • README_CN.md
    • Updated the Chinese main description to include MiniMax as a compatible API interface.
    • Added MiniMax support with native reasoning_split thinking to the Chinese features list.
  • config.example.yaml
    • Added a commented-out example configuration block for the MiniMax provider.
  • internal/constant/constant.go
    • Added a new string constant MiniMax to identify the MiniMax provider.
  • internal/registry/models/models.json
    • Added new model definitions for MiniMax-M2.5 and MiniMax-M2.5-highspeed, including their context lengths and thinking levels.
  • internal/runtime/executor/thinking_providers.go
    • Imported the new MiniMax thinking provider package.
  • internal/thinking/apply.go
    • Registered the MiniMax provider applier.
    • Modified ApplyThinking to prioritize provider-key-specific appliers when a provider key differs from the format.
    • Added a case for minimax in extractThinkingConfig to use extractMiniMaxConfig.
    • Implemented extractMiniMaxConfig to parse reasoning_split from the request body.
  • internal/thinking/provider/minimax/apply.go
    • Created a new package and file to implement the Applier interface for MiniMax, converting generic thinking configurations into MiniMax's reasoning_split boolean format.
  • internal/thinking/strip.go
    • Added minimax to the StripThinkingConfig function to remove reasoning_split and reasoning_effort fields from MiniMax requests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for the MiniMax provider, allowing users to leverage MiniMax models through the OpenAI-compatible configuration. The changes include adding MiniMax to the model registry, creating a dedicated thinking provider to handle MiniMax's native reasoning_split parameter, and enhancing the thinking application logic to prioritize provider-specific handlers. My review focuses on improving the implementation of the new MiniMax thinking provider for better clarity and maintainability. The overall implementation is solid and well-designed to accommodate providers with custom thinking formats.

Comment on lines +43 to +50
if thinking.IsUserDefinedModel(modelInfo) {
return applyMiniMax(body, config), nil
}
if modelInfo.Thinking == nil {
return body, nil
}

return applyMiniMax(body, config), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic in this Apply function can be simplified. The current structure with multiple if statements and return points can be condensed into a single conditional check, which improves readability and reduces complexity.

	if !thinking.IsUserDefinedModel(modelInfo) && modelInfo.Thinking == nil {
		return body, nil
	}
	return applyMiniMax(body, config), nil

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! Simplified the conditionals into a single check in 3e4482c.

Comment on lines +84 to +94
reasoningSplit := configToBoolean(config)

if len(body) == 0 || !gjson.ValidBytes(body) {
body = []byte(`{}`)
}

// Remove any OpenAI-style reasoning_effort that may have been set
result, _ := sjson.DeleteBytes(body, "reasoning_effort")
result, _ = sjson.SetBytes(result, "reasoning_split", reasoningSplit)

return result
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The applyMiniMax function can be refactored for better clarity by reusing the body variable instead of introducing a new result variable. This makes the data flow more straightforward and the code more concise.

	reasoningSplit := configToBoolean(config)

	if len(body) == 0 || !gjson.ValidBytes(body) {
		body = []byte(`{}`)
	}

	// Remove any OpenAI-style reasoning_effort that may have been set
	body, _ = sjson.DeleteBytes(body, "reasoning_effort")
	body, _ = sjson.SetBytes(body, "reasoning_split", reasoningSplit)

	return body

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — refactored to reuse body directly in 3e4482c.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63981af3cf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

"max_completion_tokens": 32768
}
],
"minimax": [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Register MiniMax in static model registry

Adding a minimax section in models.json is not sufficient because internal/registry/model_definitions.go still does not define or traverse a minimax field in staticModelsJSON, GetStaticModelDefinitionsByChannel, or LookupStaticModelInfo; the new entries are therefore dropped on unmarshal and never found by lookup. In practice, LookupModelInfo(model, "minimax") returns nil for these models, so MiniMax requests are treated as user-defined and bypass the capability metadata/validation this commit is trying to introduce.

Useful? React with 👍 / 👎.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! Fixed in 3e4482c — added MiniMax field to staticModelsJSON, GetMiniMaxModels() getter, case "minimax" in GetStaticModelDefinitionsByChannel, and data.MiniMax to LookupStaticModelInfo.

Address review feedback:
- Register MiniMax in staticModelsJSON struct, GetStaticModelDefinitionsByChannel,
  and LookupStaticModelInfo so model entries are properly unmarshalled and found
- Simplify Apply() by condensing two conditionals into one
- Reuse body variable in applyMiniMax() instead of introducing result

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e4482c543

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if hasThinkingConfig(config) {
return config
}
return extractOpenAIConfig(body)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse OpenAI Responses thinking for MiniMax

The MiniMax branch only falls back to extractOpenAIConfig, which reads reasoning_effort, but OpenAI Responses requests use reasoning.effort (the openai-response shape used by /responses/compact in OpenAICompatExecutor.Execute). In that path, extractThinkingConfig returns empty, hasThinkingConfig is false, and the MiniMax applier is never invoked, so reasoning_split is not produced and MiniMax-specific thinking support silently does nothing for responses traffic.

Useful? React with 👍 / 👎.

Copy link
Collaborator

@luispater luispater left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This adds MiniMax model definitions and a provider-specific thinking applier, but I found one blocking gap in the thinking pipeline.

Blocking

  • OpenAICompatExecutor still switches /responses/compact requests to the openai-response wire format, where thinking is represented as reasoning.effort. The new MiniMax path only extracts/strips/applies reasoning_split and top-level reasoning_effort, and ApplyThinking now rewrites the target format from the wire format to the provider key before extraction. As a result, MiniMax requests on /responses/compact either skip thinking conversion entirely or can retain a stale reasoning.effort field when reasoning_split is added.

Non-blocking

  • Inference from internal/registry/model_updater.go: the remote catalog refresh path still omits minimax from detectChangedProviders and validateModelsCatalog. That means MiniMax changes will not trigger refresh callbacks, and a fetched catalog without a minimax section would still be accepted.
  • I did not see test coverage for the new provider-key override path or the MiniMax applier. Please add at least one ApplyThinking case for OpenAI chat input, one for openai-response, and one static catalog load/lookup case.

Test plan

  • Not run locally per request.
  • gh pr checks 2155 reported no checks on March 16, 2026.

Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to the static model
registry. M2.7 offers 1M token context window (up from 204K on M2.5)
with 8K max output tokens and full reasoning_split thinking support.

Existing M2.5 models are retained for backward compatibility.
@octo-patch octo-patch changed the title feat: add MiniMax as first-class provider with native thinking support feat: add MiniMax as first-class provider with M2.7 models and native thinking support Mar 18, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa55e2fa26

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +105 to +108
if providerKey != providerFormat {
if keyApplier := GetProviderApplier(providerKey); keyApplier != nil {
applier = keyApplier
providerFormat = providerKey

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reuse static MiniMax metadata for compat models

When MiniMax is configured through the new openai-compatibility example, sdk/cliproxy/service.go:955-970 still registers compat.Models as UserDefined: true without copying any Thinking support, and registry.LookupModelInfo prefers that dynamic entry over the static minimax definitions (internal/registry/model_registry.go:173-176). So this new provider-key override still sends MiniMax-M2.7 down the applyUserDefinedModel path, meaning the levels/capabilities added in models.json are never used for the advertised config path and MiniMax requests keep bypassing validation/clamping.

Useful? React with 👍 / 👎.

Comment on lines +86 to +88
// Remove any OpenAI-style reasoning_effort that may have been set
body, _ = sjson.DeleteBytes(body, "reasoning_effort")
body, _ = sjson.SetBytes(body, "reasoning_split", reasoningSplit)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Drop Responses reasoning fields before setting reasoning_split

/responses/compact traffic stays in the openai-response schema, and the translator returns the raw payload when source and target are both openai-response (sdk/translator/registry.go:43-52). For requests that reach this applier via a thinking suffix, an existing reasoning.effort object therefore survives because this code only deletes top-level reasoning_effort. The forwarded MiniMax request can end up carrying both reasoning_split and the stale OpenAI Responses reasoning block, which is a schema mismatch specific to compact/Responses callers.

Useful? React with 👍 / 👎.

@octo-patch
Copy link
Author

Thanks for the thorough review @luispater! You're right about the thinking pipeline gap with the /responses/compact wire format.

I'll update the PR to handle the openai-response wire format properly, ensuring reasoning.effort is correctly mapped to/from MiniMax's thinking representation. Will push a fix shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants